package cn.foolishbird.crow.anomaly;

import cn.foolishbird.crow.core.CrowEnum;

import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * 业务断言
 *
 * @author foolish-bird
 */
public class CAssert {

    /**
     * 默认错误编号
     */
    private static final int DEFAULT_ERROR_CODE = -1;

    /**
     * 默认错误提示
     */
    private static final String DEFAULT_ERROR_MESSAGE = "系统异常";

    /**
     * List of registered AssertExceptionFactory
     */
    private static final CopyOnWriteArrayList<BsAssertExceptionFactory> REGISTERS = new CopyOnWriteArrayList<>();

    /**
     * 断言
     *
     * @param condition 断言条件
     */
    public static void assertTrue(boolean condition) {
        if (!condition) {
            throw exception(DEFAULT_ERROR_CODE, DEFAULT_ERROR_MESSAGE);
        }
    }

    /**
     * 断言
     *
     * @param condition 断言条件
     * @param content   断言失败说明
     */
    public static void assertTrue(boolean condition, String content) {
        if (!condition) {
            throw exception(DEFAULT_ERROR_CODE, content);
        }
    }

    /**
     * 断言
     *
     * @param condition 断言条件
     * @param codeState 状态美剧
     */
    public static void assertTrue(boolean condition, Enum<? extends CrowEnum> codeState) {
        if (Objects.isNull(codeState)) {
            throw exception(DEFAULT_ERROR_CODE, DEFAULT_ERROR_MESSAGE);
        }
        if (!condition) {
            CrowEnum e = (CrowEnum) codeState;
            throw exception(e.value(), e.content());
        }
    }

    /**
     * 断言
     *
     * @param condition 断言条件
     * @param code      错误编码
     * @param content   错误描述
     */
    public static void assertTrue(boolean condition, int code, String content) {
        if (!condition) {
            throw exception(code, content);
        }
    }

    /**
     * 注册异常工厂
     *
     * @param factory 异常工厂
     */
    public static void registerFactory(BsAssertExceptionFactory factory) {
        if (null == factory) {
            throw new NullPointerException();
        }
        REGISTERS.add(factory);
    }

    /**
     * 生成业务异常对象
     *
     * @param code    异常code
     * @param content 异常说明
     * @param <T>     自定义异常类型
     * @return 自定义异常类型
     */
    private static <T extends RuntimeException> RuntimeException exception(int code, String content) {
        for (BsAssertExceptionFactory<T> f : REGISTERS) {
            T e = f.exception(code, content);
            if (Objects.nonNull(e)) {
                return e;
            }
        }
        //默认用参数异常类型
        return new IllegalArgumentExceptionFactory().exception(code, content);
    }

}
